Skip to content

Add OAuth 2.0 device authorization grant (RFC 8628) - #14

Merged
mohnjiles merged 2 commits into
mainfrom
oauth-device-code-flow
Aug 9, 2026
Merged

Add OAuth 2.0 device authorization grant (RFC 8628)#14
mohnjiles merged 2 commits into
mainfrom
oauth-device-code-flow

Conversation

@mohnjiles

Copy link
Copy Markdown
Member

Summary

Adds a fourth OAuth 2.0 grant type: the device authorization flow ("device flow"). The provider hands out a short user code, LitePost shows it with a copy button, opens the verification page in the browser, and polls the token endpoint until the sign-in is approved — no redirect URI to register, no localhost callback. Requested by ionite for quicker testing against real providers.

  • New oauth2_device_flow Rust command: requests the device code, reports the user code to the UI via a flow-scoped oauth-device-prompt-{id} event, opens the browser (preferring verification_uri_complete so the code arrives pre-filled), and polls. Reuses the PendingOAuthFlows watch channel so the existing Cancel button works unchanged.
  • Poll state is decided by the response body, not the HTTP status: GitHub answers authorization_pending with 200 + form encoding where the RFC says 400 + JSON. slow_down backs off 5s per the RFC; the provider''s expires_in bounds the wait (capped at 30 min).
  • Accepts Google''s verification_url spelling alongside the RFC''s verification_uri.
  • Device prompt renders from the flow store, so the sign-in survives tab switches like the authorization code flow does.
  • OIDC discovery auto-fills the new Device Authorization URL field from device_authorization_endpoint.
  • client_secret is sent on both the device authorization request and token polls when configured, for confidential clients (e.g. OpenIddict apps that require it).
  • Docs: new Device Code section in docs/authentication.md.

Also bumps the version to 0.4.0 (all four spots + Cargo.lock).

Test plan

  • cargo test — 24/24, including new parser tests for device authorization responses (JSON/form/Google spelling/defaults) and poll outcomes (pending/slow_down/denied/token, GitHub 200-form quirk)
  • npx vitest run — 422/422, including a new component suite covering the device fields, scoped prompt event, cancel-by-flow-id, and token storage
  • npx tsc --noEmit clean; clippy warnings are pre-existing (http_client.rs)
  • Manually verified against a real OpenIddict IdP (JT) — token issued end to end
  • UI verified in dev server: grant dropdown, device fields, no callback/PKCE controls for this grant

🤖 Generated with Claude Code

mohnjiles and others added 2 commits August 9, 2026 00:20
A fourth grant type for testing APIs without registering a redirect URI:
the provider hands out a short user code, LitePost opens the verification
page in the browser and polls the token endpoint until the sign-in is
approved.

- New oauth2_device_flow command requests the device code, reports the
  user code to the UI via a flow-scoped oauth-device-prompt-{id} event
  (the command is still running while the user acts, so it cannot come
  back in the return value), opens the browser and polls. It reuses the
  PendingOAuthFlows watch channel, so the existing Cancel button works
  unchanged.
- Poll state is decided by the response body, not the HTTP status:
  GitHub answers authorization_pending with 200 and a form body where
  the RFC says 400 and JSON. slow_down adds 5s to the interval per the
  RFC, and the provider-chosen expires_in bounds the wait (capped at 30
  minutes).
- verification_url is accepted alongside verification_uri — Google
  spells it that way — and verification_uri_complete is preferred when
  opening the browser so the code arrives pre-filled.
- The user code panel renders from the flow store rather than component
  state, so a device sign-in survives switching tabs the same way the
  authorization code flow does.
- OIDC discovery auto-fills the new Device Authorization URL field from
  device_authorization_endpoint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Minor bump for the new device authorization grant. Same four spots as
always — package.json, tauri.conf.json, Cargo.toml, and the default
User-Agent header in useTabs — plus Cargo.lock via cargo.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mohnjiles
mohnjiles merged commit e32c88e into main Aug 9, 2026
2 checks passed
@mohnjiles
mohnjiles deleted the oauth-device-code-flow branch August 9, 2026 08:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants